package com.millstein.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.millstein.context.UserAuthorization;
import com.millstein.enums.BizCodeEnum;
import com.millstein.enums.user.SendCodeEnum;
import com.millstein.exception.BizException;
import com.millstein.feign.CouponFeignService;
import com.millstein.model.LoginUser;
import com.millstein.model.UserDO;
import com.millstein.mapper.UserMapper;
import com.millstein.request.NewUserCouponRequest;
import com.millstein.request.UserLoginRequest;
import com.millstein.request.UserRegisterRequest;
import com.millstein.service.NotifyService;
import com.millstein.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.millstein.util.CommonUtils;
import com.millstein.util.JsonData;
import com.millstein.util.JwtUtils;
import com.millstein.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author millstein
 * @since 2021-09-08
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {

    @Autowired
    private NotifyService notifyService;

    @Autowired
    private CouponFeignService couponFeignService;

    /**
     * 用户注册
     *      1.邮箱验证码验证
     *      2.密码加密 TODO
     *      3.账号唯一性检查 TODO
     *      4.插入数据库
     *      5.新注册用户福利发放 TODO
     *
     * @param userRegisterRequest 用户注册时的信息
     */
    @Override
    public void register(UserRegisterRequest userRegisterRequest) {
        // 校验验证码
        boolean result = notifyService.checkCode(SendCodeEnum.USER_REGISTER, userRegisterRequest.getMail(),
                userRegisterRequest.getCode());

        if (!result) {
            throw new BizException(BizCodeEnum.CODE_ERROR);
        }

        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(userRegisterRequest, userDO);
        userDO.setCreateTime(new Date());

        // 生成盐
        userDO.setSecret("$1$" + CommonUtils.getStringNumRandom(8));
        // 生成密码
        String encryptPassword = Md5Crypt.md5Crypt(userDO.getPwd().getBytes(), userDO.getSecret());
        // 设置密码
        userDO.setPwd(encryptPassword);

        // TODO 校验账号唯一性
        this.checkUnique(userRegisterRequest.getMail());

        // 保存用户信息
        if (!this.save(userDO)) {
            throw new BizException(BizCodeEnum.SAVE_FAILURE);
        }
        log.info("用户注册成功，{}", userDO);

        // TODO 发放优惠券
        this.userRegisterInitTask(userDO);
    }

    /**
     * 校验用户账号唯一（在高并发下，使用数据库的唯一索引来实现）
     * @param email 邮箱信息
     */
    private void checkUnique(String email) {

    }

    /**
     * 用户注册初始化福利信息
     * @param userDO 用户信息
     */
    private void userRegisterInitTask(UserDO userDO) {
        NewUserCouponRequest newUserCouponRequest = new NewUserCouponRequest();
        newUserCouponRequest.setName(userDO.getName());
        newUserCouponRequest.setUserId(userDO.getId());
        JsonData jsonData = couponFeignService.addNewUserCoupon(newUserCouponRequest);
        log.info("发放新用户的优惠券：{}，结果为：{}", newUserCouponRequest, jsonData);
    }

    /**
     * 用户登录
     *
     * @param userLoginRequest 用户登录时的信息
     * @return
     */
    @Override
    public String login(UserLoginRequest userLoginRequest) {
        QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
        wrapper.eq("mail", userLoginRequest.getMail());

        List<UserDO> list = this.list(wrapper);
        if (CollectionUtil.isEmpty(list)) {
            throw new BizException(BizCodeEnum.ACCOUNT_UNREGISTER);
        }

        UserDO dbUser = list.get(0);
        String password = Md5Crypt.md5Crypt(userLoginRequest.getPwd().getBytes(), dbUser.getSecret());
        if (!password.equals(dbUser.getPwd())) {
            throw new BizException(BizCodeEnum.ACCOUNT_PWD_ERROR);
        }

        log.info("用户登录成功，{}", dbUser);

        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(dbUser, loginUser);

        return JwtUtils.generateToken(loginUser);
    }

    /**
     * 查询用户自己的信息
     *
     * @return
     */
    @Override
    public UserVO findDetail() {
        LoginUser loginUser = UserAuthorization.getUserContext();
        UserDO dbUser = this.getById(loginUser.getId());
        if (dbUser == null) {
            throw new BizException(BizCodeEnum.RETURN_DATA_IS_NONE);
        }
        return new UserVO(dbUser);
    }

}
